package com.example.neuronview

import android.opengl.GLES20.*
import android.opengl.GLES30
import android.util.Log
import java.nio.IntBuffer

private val vertexShaderCode = """#version 300 es 
        layout(location=0) in vec3 vPosition;
        layout(location=1) in vec3 normal;
        uniform mat4 model;
        uniform mat4 view;
        uniform mat4 projection;
        out vec4 v_color; 
        out vec3 tnorm;
        out vec3 view_direction;
        uniform vec4 vColor;
        void main() {
          gl_Position = projection*view*model*vec4(vPosition,1.0f);
          vec4 pos_in_camera = view*model * vec4(vPosition.xyz, 1.0);
          v_color = vColor;
          tnorm = normalize((view*model*vec4(normal.xyz, 0.0)).xyz);
          view_direction = normalize(pos_in_camera.xyz);
        }"""

private val fragmentShaderCode = """#version 300 es 
    precision mediump float;
        in vec4 v_color;                          
        in vec3 tnorm;
        in vec3 view_direction;
        out vec4 fragColor;
        void main() {
          float edginess = 1.0 - abs(dot(tnorm, view_direction));
          float opacity = clamp(edginess - 0.30, 0.0, 0.5);
                               // Darken compartment at the very edge\n
          float blackness = pow(edginess, 4.0) - 0.3;
          vec3 c = mix(v_color.xyz*1.2, vec3(0, 0, 0), blackness);
          fragColor = vec4(c,opacity);
        }"""
val vertexNeuronShaderCode = """#version 300 es 
        layout(location=0) in vec3 vPosition;

        uniform mat4 model;
        uniform mat4 view;
        uniform mat4 projection;

        uniform vec4 vColor;
        out vec4 v_color;
        void main() {
          gl_Position = projection*view*model*vec4(vPosition,1.0f);
          
          v_color = vColor;

        }"""

val fragmentNeuronShaderCode = """#version 300 es 
    precision mediump float;
        in vec4 v_color;
        out vec4 fragColor;
        void main() {
          fragColor = v_color;
        }"""
class Program {
private var m_Program=0
    fun CreateProgram(vertexCode: String=vertexShaderCode,fragCode:String=fragmentShaderCode){
        // 编译顶点着色器
        val vertexShader = glCreateShader(GL_VERTEX_SHADER)
        glShaderSource(vertexShader, vertexCode)
        glCompileShader(vertexShader)
        val compileStatus0 = IntBuffer.allocate(1)
        glGetShaderiv(vertexShader, GL_COMPILE_STATUS,compileStatus0)
        if (compileStatus0[0] == GLES30.GL_FALSE) {
            val err = glGetShaderInfoLog(vertexShader)
            println(err)
        }

        // 编译片段着色器
        val fragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
        glShaderSource(fragmentShader, fragCode)
        glCompileShader(fragmentShader)
        val compileStatus = IntBuffer.allocate(1)
        glGetShaderiv(fragmentShader, GL_COMPILE_STATUS,compileStatus)
        if (compileStatus[0] == GLES30.GL_FALSE) {
            val err = glGetShaderInfoLog(fragmentShader)
            println(err)
        }
        // 链接着色器程序
        m_Program = glCreateProgram()
        glAttachShader(m_Program, vertexShader)
        glAttachShader(m_Program, fragmentShader)
        glLinkProgram(m_Program)
        val linkStatus = IntBuffer.allocate(1)
        glGetProgramiv(m_Program, GL_LINK_STATUS, linkStatus)
        if (linkStatus[0] ==GLES30.GL_FALSE) {
            val err = glGetProgramInfoLog(m_Program)
            println(err)
        }
    }
    fun Use(){
        glUseProgram(m_Program)
        var err= glGetError()
        if(err!=0)
            println(err)
    }
    fun GetAttribLocation(attrib:String):Int{
        return glGetAttribLocation(m_Program,attrib)
    }
    fun GetUniformLocation(attrib:String):Int{
        return glGetUniformLocation(m_Program,attrib)
    }
    fun GetProgram():Int{
        return m_Program
    }
}